﻿/*
	版权所有 2009-2023 荆门泽优软件有限公司
	保留所有权利
	产品首页：http://www.ncmem.com/webapp/up7/index.aspx
	联系信箱：1085617561@qq.com
	联系QQ：1085617561
    版本：7.2.10
	更新记录：
		2015-07-31 优化更新进度逻辑
*/
function HttpUploaderMgr()
{
	//根路径：http://localhost:8888/
	var pos = window.location.href.lastIndexOf("/");
    var root = [
        window.location.href.substr(0, pos + 1),
        "api/up7/"
    ].join("");

	//url=>res/
	//http://localhost:8888/filemgr/res/up6/up6.js=>
	this.getJsDir = function () {
		var js = document.scripts;
		var jsPath;
		for (var i = 0; i < js.length; i++) {
			if (js[i].src.indexOf("panel/up7.js") > -1) {
				jsPath = js[i].src.substring(0, js[i].src.indexOf("panel/up7.js"));
			}
		}
		return jsPath;
	};
	//http://localhost/res/down2/
	var pathRes = this.getJsDir() + "imgs/";
	
	var _this = this;
	this.Config = {
		  "EncodeType"		: "utf-8"
		, "Company"			: "荆门泽优软件有限公司"
		, "Version"			: "2,7,142,51656"
		, "License2"		: ""
		, "Authenticate"	: ""//域验证方式：basic,ntlm
		, "AuthName"		: ""//域帐号
		, "AuthPass"		: ""//域密码
        , "Proxy"           : {url: ""/**http://192.168.0.1:8888 */,pwd: ""/**admin:123456 */}//代理
        , "BlockCrypto"     : false//块信息加密方式
        , "BlockMD5"        : false//开启块信息验证
		, "FileMd5"         : true//是否开启md5验证功能
        , "CryptoType"      : "md5"//验证方式：md5,sha1,crc
    	, "compress": {
			open:false,//是否开启
			type: "gzip"//压缩方式：gzip,zip
		}
		, "security": {
			encrypt: false,//传输加密，需要同时配置config.json
			key: "MEQCllSLvLj65NpfSVU+vg==",
			token:false,
			algorithm: "aes"//aes,sm4
		}
        , "storage": {
			type: "io",
			oss: {
				ak: "uZUOpdpIeRZrN/aVgyQ8+azyqH5V0f4VZEEAVZogYZw=",
				sk: "h9QDauRc22NyCW2SoBjDhRvkpOdd0ul0+/eXNzc1Hw0=",
				bucket: "ncmem-temp",
				endpoint: "https://ncmem-temp.oss-cn-beijing.aliyuncs.com"
			}
		}
        , "CryptoBlockSize" : 52428800//md5验证块大小
        , "CryptoChunkSize" : 52428800//md5验证片大小
		, "FileFilter"		: "*"//文件类型。所有类型：*。自定义类型：jpg,bmp,png,gif,rar,zip,7z,doc
		, "FileSizeLimit"	: "0"//自定义允许上传的文件大小，以字节为单位。0表示不限制。字节计算工具：http://www.beesky.com/newsite/bit_byte.htm
		, "FilesLimit"		: "0"//文件选择数限制。0表示不限制
		, "AllowMultiSelect": true//多选开关。1:开启多选。0:关闭多选
		, "RangeSize"		: "10485760"//文件块大小，以字节为单位。必须为64KB的倍数。推荐大小：10MB+。
		, "Debug"			: false//是否打开调式模式。true,false
		, "LogFile"			: "F:\\log.txt"//日志文件路径。需要先打开调试模式。
		, "InitDir"			: ""//初始化路径。示例：D:\\Soft
		, "AppPath"			: ""//网站虚拟目录名称。子文件夹 web
        , "Cookie"			: ""//服务器cookie
        , "QueueCount"      : 3//同时上传的任务数
        , "FileThread"      : 3//文件块线程数，最大为10
        , "FolderThread"    : 3//文件夹上传线程数，最大为10
        , "ProcSaveTm"      : 60//定时保存进度。单位：秒，默认：1分钟
        , "AutoConnect"     : {opened:false,time:3000}//启动错误自动重传
        //文件夹操作相关
		, "UrlFdCreate"		: root+"fd_create.jsp"
		, "UrlFdComplete"	: root+"fd_complete.jsp"
		, "UrlFdDel"	    : root+"fd_del.jsp"
		//文件操作相关
		, "UrlCreate"		: root+"f_create.jsp"
		, "UrlUpdate"		: root+"f_update.jsp"
		, "UrlPost"			: root+"f_post.jsp"
		, "UrlNotice"		: root+"f_notice.jsp"
		, "UrlComplete"		: root+"f_complete.jsp"
		, "UrlList"			: root+"f_list.jsp"
		, "UrlDel"			: root+"f_del.jsp"
	    //x86
        , ie: {
              drop: { clsid: "D75AD7E8-CC9C-48BD-984C-6FBBAC1CD122", name: "Xproer.HttpDroper7" }
            , part: { clsid: "F7E405D6-AD98-4565-84FD-2AA9AED9F507", name: "Xproer.HttpPartition7" }
            , path: "http://res2.ncmem.com/download/up7/pack/2.0.22/up7.cab"
        }
	    //x64
        , ie64: {
              drop: { clsid: "DD51A458-19D2-483F-9AB1-95DC153ADD5C", name: "Xproer.HttpDroper7x64" }
            , part: { clsid: "E01D2121-3C80-4A4E-A653-6032EC552BCE", name: "Xproer.HttpPartition7x64" }
            , path: "http://res2.ncmem.com/download/up7/pack/2.0.22/up64.cab"
        }
        , firefox: { name: "", type: "application/npHttpUp7", path: "http://res2.ncmem.com/download/up7/pack/2.0.22/up7.xpi" }
        , chrome: { name: "npHttpUp7", type: "application/npHttpUp7", path: "http://res2.ncmem.com/download/up7/pack/2.0.22/up7.crx" }
        , chrome45: { name: "com.xproer.up7", path: "http://res2.ncmem.com/download/up7/pack/2.0.22/up7.crx" }
        , edge: {protocol:"up7",port:9600,visible:false}
        , exe: { path: "http://res2.ncmem.com/download/up7/pack/2.0.22/up7.exe" }
        , mac: { path: "http://res2.ncmem.com/download/up7/mac/1.0.9/up7.pkg" }
        , linux: { path: "http://res2.ncmem.com/download/up7/linux/1.0.10/com.ncmem.up7_2020.12.3-1_amd64.deb" }
        , arm64: { path: "http://res2.ncmem.com/download/up7/arm64/1.0.6/com.ncmem.up7_2020.12.3-1_arm64.deb" }
        , mips64: { path: "http://res2.ncmem.com/download/up7/mips64/1.0.5/com.ncmem.up7_2020.12.3-1_mips64el.deb" }
		, "SetupPath": "http://localhost:4955/demoAccess/js/setup.htm"
		, "Fields": { "uname": "test", "upass": "test", "uid": "0" }
		, errCode: {
			"0": "发送数据错误",
			"1": "接收数据错误",
			"2": "访问本地文件错误",
			"3": "域名未授权",
			"4": "文件大小超过限制",
			"5": "文件大小为0",
			"6": "文件被占用",
			"7": "文件夹子元素超过限制",
			"8": "文件夹大小超过限制",
			"9": "文件夹子文件大小超过限制",
			"10": "文件夹数量超过限制",
			"11": "服务器返回数据错误",
			"12": "连接服务器失败",
			"13": "请求超时",
			"14": "上传地址错误",
			"15": "文件块MD5不匹配"
		}
		, state: {
			Ready: 0,
			Posting: 1,
			Stop: 2,
			Error: 3,
			GetNewID: 4,
			Complete: 5,
			WaitContinueUpload: 6,
			None: 7,
			Waiting: 8,
			MD5Working: 9
		}
	};

	//biz event
	this.event = {
		md5Complete: function (obj/*HttpUploader对象*/, md5) { },
		fileResume: function (obj/*续传文件，参考：FileUploader*/) { },
		fileComplete: function (obj/*文件上传完毕，参考：FileUploader*/) { },
		fdComplete: function (obj/*文件夹上传完毕，参考：FolderUploader*/) { },
		fileAppend: function (obj/*添加文件，参考：FileUploader*/) { },
		fdAppend: function (obj/*添加文件夹，参考：FolderUploader*/) { },
		queueComplete: function () {/*队列上传完毕*/ },
		loadComplete: function (m) {/*控件加载完毕*/ }
	};
    this.data = {
        browser: { name: navigator.userAgent.toLowerCase(), ie: true, ie64: false, firefox: false, chrome: false, edge: false, arm64: false, mips64: false },
        cmps: []/**已上传完的文件对象列表 */
    };
	this.ui = {
		render: null, btn: { selFile: null, selFolder: null, paste: null, clear: null, setup: null, setupCmp: null },
		ico: {
			file: pathRes + "32/file.png",
			file_up: pathRes + "32/file-up.png",
			file_ok: pathRes + "32/file-ok.png",
			file_err: pathRes + "32/file-err.png",
			file_sec: pathRes + "32/file-sec.png",
			file_quk: pathRes + "32/file-quk.png",
			file_chk: pathRes + "32/file-chk.png",
			file_wait: pathRes + "32/file-wait.png",
			folder: pathRes + "32/folder.png",
			dir_ok: pathRes + "32/dir-ok.png",
			dir_up: pathRes + "32/dir-up.png",
			dir_err: pathRes + "32/dir-err.png",
			dir_sec: pathRes + "32/dir-sec.png",
			dir_scn: pathRes + "32/dir-scn.png",
			dir_wait: pathRes + "32/dir-wait.png",
			stop: pathRes + "32//stop.png",
			cancel: pathRes + "32//stop.png",
			del: pathRes + "32/del.png",
			post: pathRes + "32/post.png",
			upFile: pathRes + "16/file.png",
			upFolder: pathRes + "16/folder.png",
			paste: pathRes + "16/paste.png",
			clear: pathRes + "16/clear.png",
			setup: pathRes + "16/setup.png",
			ok: pathRes + "16/ok.png"
		}
	};

	if (arguments.length > 0) {
		var par = arguments[0];
		if (typeof (par.Config) != "undefined") $.extend(true,this.Config, par.Config);
		if (typeof (par.event) != "undefined") $.extend(true,this.event, par.event);
		if (typeof (par.ui) != "undefined") $.extend(true,this.ui, par.ui);
	}

	this.FileFilter = new Array(); //文件过滤器
	this.idCount = 1; 	//上传项总数，只累加
	this.filesMap = new Object(); //本地文件列表映射表
	this.QueueFiles = new Array();//文件队列，数据:id1,id2,id3
	this.QueueWait = new Array(); //等待队列，数据:id1,id2,id3
	this.QueuePost = new Array(); //上传队列，数据:id1,id2,id3
	this.filesUI = null;//上传列表面板
	this.parter = null;
	this.Droper = null;
	this.tmpFile = null;
	this.tmpFolder = null;
	this.tmpSpliter = null;
	this.uiSetupTip = null;
	//检查版本 Win32/Win64/Firefox/Chrome
    this.data.browser.ie = this.data.browser.name.indexOf("msie") > 0;
	//IE11检查
    this.data.browser.ie = this.data.browser.ie ? this.data.browser.ie : this.data.browser.name.search(/(msie\s|trident.*rv:)([\w.]+)/) != -1;
    this.data.browser.firefox = this.data.browser.name.indexOf("firefox") > 0;
    this.data.browser.chrome = this.data.browser.name.indexOf("chrome") > 0;
    this.data.browser.mips64 = this.data.browser.name.indexOf("mips64") > 0;
    this.data.browser.arm64 = this.data.browser.name.indexOf("aarch64") > 0;
    this.data.browser.edge = this.data.browser.name.indexOf("edge") > 0;
	this.pluginInited = false;
	this.edgeApp = new Uploader7Svr(this);
	this.edgeApp.ent.on_close = function () { _this.socket_close(); };
	this.app = new Uploader7App(this);
    if (this.data.browser.edge) { this.data.browser.ie = this.data.browser.firefox = this.data.browser.chrome = false; }

	//容器的HTML代码
	this.GetHtmlContainer = function () {
		//npapi
		var html = "";
        if (this.data.browser.ie) {
			//拖拽组件
			//com += '<object name="droper" classid="clsid:' + this.Config.ie.drop.clsid + '"';
			//com += ' codebase="' + this.Config.ie.path + '#version=' + this.Config.Version + '" width="192" height="192" >';
			//com += '</object>';
		}
        if (this.data.browser.edge) html = '';
		//文件夹选择控件
		html += '<object name="parter" classid="clsid:' + this.Config.ie.part.clsid + '"';
		html += ' codebase="' + this.Config.ie.path + '#version=' + this.Config.Version + '" width="1" height="1" ></object>';

		//ui
		html += '<div name="files-panel" class="files-panel">';

		//上传列表项模板
		html += '<div class="file-item" id="tmpFile" name="fileItem">\
                    <div class="img-box"><img name="file"/></div>\
					<div class="area-l">\
						<div class="file-head">\
						    <div name="fileName" class="name">HttpUploader程序开发.pdf</div>\
						    <div name="percent" class="percent">(35%)</div>\
						    <div name="fileSize" class="size" child="1">1000.23MB</div>\
                        </div>\
						<div class="process-border"><div name="process" class="process"></div></div>\
						<div name="msg" class="msg top-space">15.3MB 20KB/S 10:02:00</div>\
					</div>\
					<div class="area-r">\
                        <span class="btn-box" style="display:none" name="post" title="继续"><img name="post"/><div>继续</div></span>\
                        <span class="btn-box" name="cancel" title="取消"><img name="cancel" /><div>取消</div></span>\
						<span class="btn-box" style="display:none" name="stop" title="停止"><img name="stop"/><div>停止</div></span>\
						<span class="btn-box" style="display:none" name="del" title="删除"><img name="del"/><div>删除</div></span>\
					</div>';
		html += '</div>';
		//文件夹模板
		html += '<div class="file-item" name="folderItem">\
					<div class="img-box"><img name="folder"/></div>\
					<div class="area-l">\
						<div class="file-head">\
						    <div name="fileName" class="name">HttpUploader程序开发.pdf</div>\
						    <div name="percent" class="percent">(35%)</div>\
						    <div name="fileSize" class="size" child="1">1000.23MB</div>\
                        </div>\
						<div class="process-border top-space"><div name="process" class="process"></div></div>\
						<div name="msg" class="msg top-space">15.3MB 20KB/S 10:02:00</div>\
					</div>\
					<div class="area-r">\
                        <span class="btn-box" style="display:none" name="post" title="继续"><img name="post"/><div>继续</div></span>\
                        <span class="btn-box" name="cancel" title="取消"><img name="cancel" /><div>取消</div></span>\
						<span class="btn-box" style="display:none" name="stop" title="停止"><img name="stop"/><div>停止</div></span>\
						<span class="btn-box" style="display:none" name="del" title="删除"><img name="del"/><div>删除</div></span>\
					</div>';
		html += '</div>';
		//分隔线
		html += '<div class="file-line" name="lineSplite"></div>';
		//上传列表
		html += '<div name="post_panel">\
					<div name="post_head" class="files-toolbar">\
						<span class="tool-btn" style="display:none" name="btnAddFiles"><img name="upFile"/>上传文件</span>\
						<span class="tool-btn" style="display:none" name="btnAddFolder"><img name="upFolder"/>上传目录</span>\
						<span class="tool-btn" style="display:none" name="btnPasteFile"><img name="paste"/>粘贴</span>\
						<span class="tool-btn" style="display:none" name="btnClear"><img name="clear"/>清理</span>\
						<span class="tool-btn" name="btnSetup"><img name="setup"/>安装控件</span>\
                        <span class="tool-btn" name="btnSetupCmp"><img name="ok"/>我已安装</span>\
					</div>\
					<div name="post_content">\
						<div name="post_body" class="file-post-view"></div>\
					</div>\
				</div>';
		html += '</div>';
		return html;
	};

	//打开上传面板
	this.OpenPnlUpload = function () {
		$("#liPnlUploader").click();
	};
	//打开文件列表面板
	this.OpenPnlFiles = function () {
		$("#liPnlFiles").click();
	};

    this.set_config = function (v) { $.extend(this.Config, v); };
	this.open_files = function (json) {
		for (var i = 0, l = json.files.length; i < l; ++i) {
			this.addFileLoc(json.files[i]);
		}
		setTimeout(function () { _this.PostFirst(); }, 500);
	};
	this.open_folders = function (json) {
		this.addFolderLoc(json);
		setTimeout(function () { _this.PostFirst(); }, 500);
	};
	this.paste_files = function (json) {
		for (var i = 0, l = json.files.length; i < l; ++i) {
			this.addFileLoc(json.files[i]);
		}
	};
	this.paste_folders = function (json) {
		for (var i = 0, l = json.folders.length; i < l; ++i) {
			this.addFolderLoc(json.folders[i]);
		}
		setTimeout(function () { _this.PostFirst(); }, 500);
	};
	this.post_process = function (json) {
		var p = this.filesMap[json.id];
		p.post_process(json);
	};
	this.post_error = function (json) {
		var p = this.filesMap[json.id];
		p.post_error(json);
	};
	this.post_stoped = function (json) {
		var p = this.filesMap[json.id];
		p.post_stoped(json);
	};
	this.post_complete = function (json) {
		var p = this.filesMap[json.id];
		p.post_complete(json);
	};
	this.md5_process = function (json) {
		var p = this.filesMap[json.id];
		p.md5_process(json);
	};
	this.md5_complete = function (json) {
		var p = this.filesMap[json.id];
		p.md5_complete(json);
	};
	this.md5_error = function (json) {
		var p = this.filesMap[json.id];
		p.md5_error(json);
	};
	this.scan_process = function (json) {
		var p = this.filesMap[json.id];
		p.scan_process(json);
	};
	this.scan_complete = function (json) {
		var p = this.filesMap[json.id];
		p.scan_complete(json);
	};
	this.load_complete = function (json) {
		this.pluginInited = true;

        this.ui.btn.selFile.show();
        this.ui.btn.selFolder.show();
        this.ui.btn.paste.show();
        this.ui.btn.clear.show();
        this.ui.btn.setup.hide();
        this.ui.btn.setupCmp.hide();

		var needUpdate = true;
		if (typeof (json.version) != "undefined") {
			if (json.version == this.Config.Version) {
				needUpdate = false;
			}
		}
        if (needUpdate) this.update_notice();
        else { this.ui.btn.setup.hide(); }
		setTimeout(function () {
			//_this.load_files();
		}, 400);
		this.event.loadComplete(this);
	};
	this.load_complete_edge = function (json) {
		this.pluginInited = true;
        this.ui.btn.setup.hide();
		_this.app.init();
	};
	this.socket_close = function () {
		while (_this.QueuePost.length > 0) {
			_this.filesMap[_this.QueuePost[0]].post_stoped(null);
		}
		_this.QueuePost.length = 0;
		this.ui.btn.selFile.hide();
		this.ui.btn.selFolder.hide();
		this.ui.btn.paste.hide();
		this.ui.btn.clear.hide();
		this.ui.btn.setup.show();
		this.ui.btn.setupCmp.show();
	};
	this.recvMessage = function (str) {
		var json = JSON.parse(str);
		if (json.name == "open_files") { _this.open_files(json); }
		else if (json.name == "open_folders") { _this.open_folders(json); }
		else if (json.name == "paste_files") { _this.paste_files(json); }
		else if (json.name == "paste_folders") { _this.paste_folders(json); }
		else if (json.name == "post_process") { _this.post_process(json); }
		else if (json.name == "post_error") { _this.post_error(json); }
		else if (json.name == "post_stoped") { _this.post_stoped(json); }
		else if (json.name == "post_complete") { _this.post_complete(json); }
		else if (json.name == "md5_process") { _this.md5_process(json); }
		else if (json.name == "md5_complete") { _this.md5_complete(json); }
		else if (json.name == "md5_error") { _this.md5_error(json); }
		else if (json.name == "scan_process") { _this.scan_process(json); }
		else if (json.name == "scan_complete") { _this.scan_complete(json); }
		else if (json.name == "load_complete") { _this.load_complete(json); }
		else if (json.name == "load_complete_edge") { _this.load_complete_edge(json); }
		else if (json.name == "extension_complete") {
			setTimeout(function () {
				var param = { name: "init", config: _this.Config };
				_this.app.postMessage(param);
			}, 1000);
		}
	};

	this.pluginLoad = function () {
		if (!this.pluginInited) {
            if (this.data.browser.edge) {
				this.edgeApp.connect();
			}
		}
	};
	this.pluginCheck = function () {
		if (!this.pluginInited) {
			alert("控件没有加载成功，请安装控件或等待加载。");
			this.pluginLoad();
			return false;
		}
		return true;
	};

	//APIs
	this.openFile = function () {
		if (!this.pluginCheck()) return;
		_this.app.openFiles();
	};

	//打开文件夹选择对话框
	this.openFolder = function () {
		if (!this.pluginCheck()) return;
		_this.app.openFolders();
	};

	//粘贴文件
	this.pasteFiles = function () {
		if (!this.pluginCheck()) return;
		_this.app.pasteFiles();
	};

	this.addFile = function (path) {
		if (!this.pluginCheck()) return;
		this.app.addFile({ pathLoc: path });
	};
	this.addFolder = function (path) {
		if (!this.pluginCheck()) return;
		this.app.addFolder({ pathLoc: path });
	};

	this.checkBrowser = function () {
		//Win64
		if (window.navigator.platform == "Win64") {
            $.extend(this.Config.ie, this.Config.ie64);
		}//macOS
		else if (window.navigator.platform == "MacIntel") {
            this.data.browser.edge = true;
			this.app.postMessage = this.app.postMessageEdge;
			this.edgeApp.run = this.edgeApp.runChr;
			this.Config.exe.path = this.Config.mac.path;
		}//linux
		else if (window.navigator.platform == "Linux x86_64") {
            this.data.browser.edge = true;
			this.app.postMessage = this.app.postMessageEdge;
			this.edgeApp.run = this.edgeApp.runChr;
			this.Config.exe.path = this.Config.linux.path;
        }//Linux aarch64
        else if (this.data.browser.arm64) {
            this.data.browser.edge = true;
            this.app.postMessage = this.app.postMessageEdge;
            this.edgeApp.run = this.edgeApp.runChr;
            this.Config.exe.path = this.Config.arm64.path;
        }//Linux mips64
        else if (this.data.browser.mips64) {
            this.data.browser.edge = true;
            this.app.postMessage = this.app.postMessageEdge;
            this.edgeApp.run = this.edgeApp.runChr;
            this.Config.exe.path = this.Config.mips64.path;
        }
        else if (this.data.browser.firefox) {
            this.data.browser.edge = true;
			this.app.postMessage = this.app.postMessageEdge;
			this.edgeApp.run = this.edgeApp.runChr;
		}
        else if (this.data.browser.chrome) {
            this.data.browser.edge = true;
            this.app.check = this.app.checkFF;
            $.extend(this.Config.firefox, this.Config.chrome);
			this.app.postMessage = this.app.postMessageEdge;
			this.edgeApp.run = this.edgeApp.runChr;
		}
        else if (this.data.browser.edge) {
			this.app.postMessage = this.app.postMessageEdge;
		}
	};
	this.checkBrowser();

	//升级通知
	this.update_notice = function () {
        this.ui.btn.setup.text("升级控件");
        this.ui.btn.setup.css("color", "red");
        this.ui.btn.setup.show();
	};

	//安全检查，在用户关闭网页时自动停止所有上传任务。
	this.SafeCheck = function (event) {
		$(window).bind("beforeunload", function (event) {
			if (_this.QueuePost.length > 0) {
				event.returnValue = "您还有程序正在运行，确定关闭？";
			}
		});

		$(window).bind("unload", function () {
            if (_this.data.browser.edge) _this.edgeApp.close();
			if (_this.QueuePost.length > 0) {
				_this.StopAll();
			}
		});
	};

	//加载容器，上传面板，文件列表面板
	this.load_to = function(o)
	{
	    var dom = o.append(this.GetHtmlContainer());
	    this.initUI(dom);
	};

	this.initUI = function (dom) {
		//var filesSvr = dom.find('li[name="filesSvr"]');
		//var filesLoc = dom.find('li[name="filesLoc"]');
		this.parter = dom.find('embed[name="ffParter"]').get(0);
		this.ieParter = dom.find('object[name="parter"]').get(0);
		this.Droper = dom.find('object[name="droper"]').get(0);

		//var panel = filesLoc.html(this.GetHtmlFiles());
		var panel = dom.find('div[name="files-panel"]');

		//更新图标
		$.each(this.ui.ico, function (i, n) {
			panel.find("img[name=\"" + i + "\"]").attr("src", n);
		});
		//var post_panel = dom.find("div[name='tab-body']");
		var post_body = dom.find("div[name='post_body']");
		var post_head = dom.find('div[name="post_head"]');
		//var post_foot = dom.find('div[name="post_footer"]');
		post_body.height(panel.height() - post_head.height());

		this.filesUI = post_body;
		this.tmpFile = panel.find('div[name="fileItem"]');
		this.tmpFolder = panel.find('div[name="folderItem"]');
		this.tmpSpliter = panel.find('div[name="lineSplite"]');
		this.pnlHeader = panel.find('div[name="pnlHeader"]');
        this.ui.btn.selFile = panel.find('span[name="btnAddFiles"]');
        this.ui.btn.selFolder = panel.find('span[name="btnAddFolder"]');
        this.ui.btn.paste = panel.find('span[name="btnPasteFile"]');
        this.ui.btn.clear = panel.find('span[name="btnClear"]');
        this.ui.btn.setup = panel.find('span[name="btnSetup"]');
        this.ui.btn.setupCmp = panel.find('span[name="btnSetupCmp"]');
        this.ui.btn.setup.click(function () { window.open(_this.Config.exe.path); });
        this.ui.btn.setupCmp.click(function () { _this.edgeApp.connect(); });

        post_head.find('.tool-btn').each(function ()
        {
			$(this).hover(function () {
				$(this).addClass("tool-btn-hover");
			}, function () {
					$(this).removeClass("tool-btn-hover");
			});
		});
		//添加多个文件
        this.ui.btn.selFile.click(function () { _this.openFile(); });
		//添加文件夹
        this.ui.btn.selFolder.click(function () { _this.openFolder(); });
		//粘贴文件
        this.ui.btn.paste.click(function () { _this.pasteFiles(); });
		//清空已完成文件
        this.ui.btn.clear.click(function () { _this.ClearComplete(); });

		this.SafeCheck();

		setTimeout(function () {
            if (!_this.data.browser.edge) {
                if (_this.data.browser.ie) {
					_this.parter = _this.ieParter;
					if (null != _this.Droper) _this.Droper.recvMessage = _this.recvMessage;
				}
				_this.parter.recvMessage = _this.recvMessage;
			}

            if (_this.data.browser.edge) {
				_this.edgeApp.connect();
			}
			else {
				_this.app.init();
			}
		}, 500);
	};

	//清除已完成文件
	this.ClearComplete = function () {
        $.each(this.data.cmps, function (i, n) { n.remove(); });
        this.data.cmps.length = 0;
	};

	//上传队列是否已满
	this.IsPostQueueFull = function () {
		//目前只支持同时上传三个文件
		return (_this.QueuePost.length + 1) > this.Config.QueueCount;
	};

	//添加到上传队列
	this.AppendQueuePost = function (fid) {
		_this.QueuePost.push(fid);
	};

	//从上传队列删除
	this.RemoveQueuePost = function (fid) {
		if (_this.QueuePost.length < 1) return;
		this.QueuePost = $.grep(this.QueuePost, function (n, i) {
			return n == fid;
		}, true);
	};

	//添加到上传队列
	this.AppendQueue = function (fid) {
		_this.QueueFiles.push(fid);
	};

	//从队列中删除
	this.RemoveQueue = function (fid) {
		if (this.QueueFiles.length < 1) return;
		this.QueueFiles = $.grep(this.QueueFiles, function (n, i) {
			return n == fid;
		}, true);
	};

	//添加到未上传ID列表，(停止，出错)
	this.AppendQueueWait = function (fid) {
		_this.QueueWait.push(fid);
	};

	//从未上传ID列表删除，(上传完成)
	this.RemoveQueueWait = function (fid) {
		if (this.QueueWait.length < 1) return;
		this.QueueWait = $.grep(this.QueueWait, function (n, i) {
			return n == fid;
		}, true);
	};

	//停止所有上传项
	this.StopAll = function () {
		for (var i = 0, l = _this.QueuePost.length; i < l; ++i) {
			_this.filesMap[_this.QueuePost[i]].stop_manual();
		}
		_this.QueuePost.length = 0;
	};

	//传送当前队列的第一个文件
	this.PostFirst = function () {
		//上传列表不为空
		if (_this.QueueFiles.length > 0) {
			while (_this.QueueFiles.length > 0) {
				//上传队列已满
				if (_this.IsPostQueueFull()) return;
				var index = _this.QueueFiles.shift();
				_this.filesMap[index].post();
			}
		}
	};

	//启动下一个传输
	this.PostNext = function () {
		if (this.IsPostQueueFull()) return; //上传队列已满

		if (this.QueueFiles.length > 0) {
			var index = this.QueueFiles.shift();
			var obj = this.filesMap[index];

			//空闲状态
			if (this.Config.state.Ready == obj.State) {
				obj.post();
			}
		} //全部上传完成
		else {
			if (this.QueueFiles.length == 0//文件队列为空
				&& this.QueuePost.length == 0//上传队列为空
				&& this.QueueWait.length == 0)//等待队列为空
			{
				this.event.queueComplete();
			}
		}
	};

	/*
	验证文件名是否存在
	参数:
	[0]:文件名称
	*/
	this.Exist = function () {
		var fn = arguments[0];

		for (a in _this.filesMap) {
			if (_this.filesMap[a].LocalFile == fn) {
				return true;
			}
		}
		return false;
	};

	/*
	根据ID删除上传任务
	参数:
		fid 上传项ID。唯一标识
	*/
	this.Delete = function (id) {
		_this.filesMap[id].LocalFile = null;
		_this.RemoveQueue(id); //从队列中删除
		_this.RemoveQueueWait(id);//从未上传列表中删除
	};

	/*
	判断文件类型是否需要过滤
	根据文件后缀名称来判断。
	*/
	this.NeedFilter = function (fname) {
		if (_this.FileFilter.length == 0) return false;
		var exArr = fname.split(".");
		var len = exArr.length;
		if (len > 0) {
			for (var i = 0, l = _this.FileFilter.length; i < l; ++i) {
				//忽略大小写
				if (_this.FileFilter[i].toLowerCase() == exArr[len - 1].toLowerCase()) {
					return true;
				}
			}
		}
		return false;
	};

	this.ResumeFile = function (fileSvr) {
		//本地文件名称存在
		if (_this.Exist(fileSvr.pathLoc)) return;
		var uper = this.addFileLoc(fileSvr);
		uper.svr_inited = true;

		setTimeout(function () { _this.PostFirst(); }, 500);
	};

	//fileLoc:name,id,ext,size,length,pathLoc,md5,lenSvr,idSvr
	this.addFileLoc = function (fileLoc) {
		//本地文件名称存在
		if (_this.Exist(fileLoc.pathLoc)) return;
		//此类型为过滤类型
		if (_this.NeedFilter(fileLoc.ext)) return;

		var nameLoc = fileLoc.nameLoc;
		_this.AppendQueue(fileLoc.id);//添加到队列

		var ui = _this.tmpFile.clone();//文件信息
		var sp = _this.tmpSpliter.clone();//分隔线
		_this.filesUI.append(ui);//添加文件信息
		_this.filesUI.append(sp);//添加分隔线
		ui.css("display", "block");
		sp.css("display", "block");

		var uiName = ui.find("div[name='fileName']");
		var uiSize = ui.find("div[name='fileSize']")
		var uiProcess = ui.find("div[name='process']");
		var uiMsg = ui.find("div[name='msg']");
		var btnCancel = ui.find("span[name='cancel']");
		var btnPost = ui.find("span[name='post']");
		var btnStop = ui.find("span[name='stop']");
		var btnDel = ui.find("span[name='del']");
		var uiPercent = ui.find("div[name='percent']");

		var upFile = new FileUploader(fileLoc, _this);
		this.filesMap[fileLoc.id] = upFile;//添加到映射表
		var ui_eles = {
			ico: { state: ui.find('img[name="file"]')},
			msg: uiMsg, process: uiProcess, percent: uiPercent,
			btn: { del: btnDel, cancel: btnCancel, post: btnPost, stop: btnStop },
			div: ui, split: sp
		};
		upFile.ui = ui_eles;

		uiName.text(nameLoc).attr("title", nameLoc);
		uiSize.text(fileLoc.sizeLoc);
		uiMsg.text("");
		uiPercent.text("(0%)");

		upFile.Ready(); //准备
		this.event.fileAppend(upFile);
		return upFile;
	};

	//添加文件夹,json为文件夹信息字符串
	this.addFolderLoc = function (json) {
		var fdLoc = json;
		//本地文件夹存在
		if (this.Exist(fdLoc.pathLoc)) return;
		//针对空文件夹的处理
        if (json.files == null) $.extend(fdLoc, { files: [] });
		//if (json.lenLoc == 0) return;

		this.AppendQueue(json.id);//添加到队列

		var ui = this.tmpFolder.clone();//文件夹信息
		var sp = this.tmpSpliter.clone();//分隔线
		this.filesUI.append(ui);//添加到上传列表面板
		this.filesUI.append(sp);
		ui.css("display", "block");
		sp.css("display", "block");

		var uiName = ui.find("div[name='fileName']");
		var uiSize = ui.find("div[name='fileSize']")
		var divProcess = ui.find("div[name='process']");
		var divMsg = ui.find("div[name='msg']");
		var btnCancel = ui.find("span[name='cancel']");
		var btnPost = ui.find("span[name='post']");
		var btnStop = ui.find("span[name='stop']");
		var btnDel = ui.find("span[name='del']");
		var divPercent = ui.find("div[name='percent']");
		var ui_eles = {
			ico: {state:ui.find('img[name="folder"]')},
			msg: divMsg, size: uiSize, process: divProcess, percent: divPercent,
			btn: { del: btnDel, cancel: btnCancel, post: btnPost, stop: btnStop },
			split: sp, div: ui
		};

		divPercent.text("(" + fdLoc.perSvr + ")");
		divProcess.css("width", fdLoc.perSvr);
		divMsg.text("");
		//if(fdLoc.fdName != null) fdLoc.name = fdLoc.fdName;
		uiName.text(fdLoc.nameLoc);
		uiName.attr("title", fdLoc.nameLoc + "\n文件：" + fdLoc.files.length + "\n文件夹：" + fdLoc.foldersCount + "\n大小：" + fdLoc.sizeLoc);
		uiSize.text(fdLoc.sizeLoc);

		var fdTask = new FolderUploader(fdLoc, this);
		this.filesMap[json.id] = fdTask;//添加到映射表
		fdTask.ui = ui_eles;
		fdTask.Ready(); //准备
		this.event.fdAppend(fdTask);
		return fdTask;
	};

	this.ResumeFolder = function (fileSvr) {
		var fd = this.addFolderLoc(fileSvr);
		fd.folderInit = true;
		fd.folderScan = true;
	};

	//加载未完成列表
	this.load_files = function () {
		var param = $.extend({}, this.Config.Fields, { time: new Date().getTime() });
		$.ajax({
			type: "GET"
			, dataType: 'jsonp'
			, jsonp: "callback" //自定义的jsonp回调函数名称，默认为jQuery自动生成的随机函数名
			, url: this.Config["UrlList"]
			, data: param
			, success: function (msg) {
				if (msg.value != null) {
					var files = JSON.parse(decodeURIComponent(msg.value));
					$.each(files, function (i, n) {
						if (n.fdTask) {
							var fd = _this.addFolderLoc(n);
							if (null == fd) return;
							fd.folderInit = true;
							fd.folderScan = true;
							fd.ui.percent.text("(" + n.perSvr + ")");
							fd.ui.process.css("width", n.perSvr);
							fd.ui.btn.post.show();
							fd.ui.btn.cancel.show();
							_this.RemoveQueue(fd.folderSvr.id);
						}
						else {
							var f = _this.addFileLoc(n);
							if (null == f) return;
							f.svr_inited = true;
							f.ui.percent.text("(" + n.perSvr + ")");
							f.ui.process.css("width", n.perSvr);
							f.ui.btn.post.show();
							f.ui.btn.cancel.show();
							_this.RemoveQueue(f.fileSvr.id);
						}
					});
				}
			}
			, error: function (req, txt, err) { alert("加载文件列表错误！" + req.responseText); }
			, complete: function (req, sta) { req = null; }
		});
	};
	
	//加载
	if (typeof (this.ui.render) == "string") {
		$(function () {
			_this.load_to($("#" + _this.ui.render));
		})
	}
	else if (typeof (this.ui.render) == "object") {
		this.load_to(this.ui.render);
	}
}